#include <sys/cdefs.h>

#if __LP64__
#   define PTR " .quad " 
#   define PTRSIZE "8"
#   define LOGPTRSIZE "3"
#else
#   define PTR " .long " 
#   define PTRSIZE "4"
#   define LOGPTRSIZE "2"
#endif

#if __has_feature(ptrauth_calls)
#   define SIGNED_METHOD_LIST_IMP "@AUTH(ia,0,addr) "
#else
#   define SIGNED_METHOD_LIST_IMP
#endif

#define str(x) #x
#define str2(x) str(x)

// Swift metadata initializers. Define these in the test.
EXTERN_C Class initSuper(Class cls, void *arg);
EXTERN_C Class initSub(Class cls, void *arg);

@interface SwiftSuper : NSObject @end
@interface SwiftSub : SwiftSuper @end

__BEGIN_DECLS
// not id to avoid ARC operations because the class doesn't implement RR methods
void* nop(void* self) { return self; }
__END_DECLS

asm(
    ".globl _OBJC_CLASS_$_SwiftSuper    \n"
    ".section __DATA,__objc_data  \n"
    ".align 3                     \n"
    "_OBJC_CLASS_$_SwiftSuper:          \n"
    PTR "_OBJC_METACLASS_$_SwiftSuper   \n"
    PTR "_OBJC_CLASS_$_NSObject         \n"
    PTR "__objc_empty_cache \n"
    PTR "0 \n"
    PTR "L_ro + 2 \n"
    // pad to OBJC_MAX_CLASS_SIZE
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    ""
    "_OBJC_METACLASS_$_SwiftSuper:          \n"
    PTR "_OBJC_METACLASS_$_NSObject   \n"
    PTR "_OBJC_METACLASS_$_NSObject   \n"
    PTR "__objc_empty_cache \n"
    PTR "0 \n"
    PTR "L_meta_ro \n"
    // pad to OBJC_MAX_CLASS_SIZE
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    ""
    "L_ro: \n"
    ".long (1<<6)\n"
    ".long 0 \n"
    ".long "PTRSIZE" \n"
#if __LP64__
    ".long 0 \n"
#endif
    PTR "0 \n"
    PTR "L_super_name \n"
    PTR "L_good_methods \n"
    PTR "0 \n"
    PTR "L_super_ivars \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "_initSuper" SIGNED_METHOD_LIST_IMP "\n"
    ""
    "L_meta_ro: \n"
    ".long 1 \n"
    ".long 40 \n"
    ".long 40 \n"
#if __LP64__
    ".long 0 \n"
#endif
    PTR "0 \n"
    PTR "L_super_name \n"
    PTR "L_good_methods \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"

    ".globl _OBJC_CLASS_$_SwiftSub    \n"
    ".section __DATA,__objc_data  \n"
    ".align 3                     \n"
    "_OBJC_CLASS_$_SwiftSub:          \n"
    PTR "_OBJC_METACLASS_$_SwiftSub   \n"
    PTR "_OBJC_CLASS_$_SwiftSuper       \n"
    PTR "__objc_empty_cache \n"
    PTR "0 \n"
    PTR "L_sub_ro + 2 \n"
    // pad to OBJC_MAX_CLASS_SIZE
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    ""
    "_OBJC_METACLASS_$_SwiftSub:          \n"
    PTR "_OBJC_METACLASS_$_NSObject   \n"
    PTR "_OBJC_METACLASS_$_SwiftSuper        \n"
    PTR "__objc_empty_cache \n"
    PTR "0 \n"
    PTR "L_sub_meta_ro \n"
    // pad to OBJC_MAX_CLASS_SIZE
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    ""
    "L_sub_ro: \n"
    ".long (1<<6)\n"
    ".long 0 \n"
    ".long "PTRSIZE" \n"
#if __LP64__
    ".long 0 \n"
#endif
    PTR "0 \n"
    PTR "L_sub_name \n"
    PTR "L_good_methods \n"
    PTR "0 \n"
    PTR "L_sub_ivars \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "_initSub" SIGNED_METHOD_LIST_IMP "\n"
    ""
    "L_sub_meta_ro: \n"
    ".long 1 \n"
    ".long 40 \n"
    ".long 40 \n"
#if __LP64__
    ".long 0 \n"
#endif
    PTR "0 \n"
    PTR "L_sub_name \n"
    PTR "L_good_methods \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"
    PTR "0 \n"

    "L_good_methods: \n"
    ".long 3*"PTRSIZE" \n"
    ".long 1 \n"
    PTR "L_self \n"
    PTR "L_self \n"
    PTR "_nop" SIGNED_METHOD_LIST_IMP "\n"

    "L_super_ivars: \n"
    ".long 4*"PTRSIZE" \n"
    ".long 1 \n"
    PTR "L_super_ivar_offset \n"
    PTR "L_super_ivar_name \n"
    PTR "L_super_ivar_type \n"
    ".long "LOGPTRSIZE" \n"
    ".long "PTRSIZE" \n"

    "L_sub_ivars: \n"
    ".long 4*"PTRSIZE" \n"
    ".long 1 \n"
    PTR "L_sub_ivar_offset \n"
    PTR "L_sub_ivar_name \n"
    PTR "L_sub_ivar_type \n"
    ".long "LOGPTRSIZE" \n"
    ".long "PTRSIZE" \n"

    "L_super_ivar_offset: \n"
    ".long 0 \n"
    "L_sub_ivar_offset: \n"
    ".long "PTRSIZE" \n"

    ".cstring \n"
    "L_super_name:       .ascii \"SwiftSuper\\0\" \n"
    "L_sub_name:         .ascii \"SwiftSub\\0\" \n"
    "L_load:             .ascii \"load\\0\" \n"
    "L_self:             .ascii \"self\\0\" \n"
    "L_super_ivar_name:  .ascii \"super_ivar\\0\" \n"
    "L_super_ivar_type:  .ascii \"c\\0\" \n"
    "L_sub_ivar_name:    .ascii \"sub_ivar\\0\" \n"
    "L_sub_ivar_type:    .ascii \"@\\0\" \n"


    ".section __DATA,__objc_classlist \n"
    PTR "_OBJC_CLASS_$_SwiftSuper \n"
    PTR "_OBJC_CLASS_$_SwiftSub \n"

    ".text \n"
);

void fn(void) { }
